<script>
import {
  ref,
  h,
  defineComponent,
  resolveComponent,
  onMounted,
  Transition
} from 'vue'

export default defineComponent({
  props: [
    'name',
    'style',
    'imgSrc',
    'width',
    'height',
    'fit',
    'description'
  ],
  setup({
    name = '',
    style = '',
    imgSrc = '',
    description,
    ...imgProps
  }) {
    const LazyComponent = resolveComponent('lazy-component')
    const VanImage = resolveComponent('van-image')

    const show = ref(false)
    const parentComponentMounted = ref(false)
    const children = () => h('div', {
      class: ['animate-image--box'],
      'data-animate': name
    }, [
      h(VanImage, {
        ...imgProps,
        src: imgSrc
      }),
      description && h('div', {
        class: ['image-description']
      }, [
        h('span', description)
      ])
    ])

    function imageLoadedAsync(src, callback) {
      if (!src) return callback({ src })

      const image = new Image()

      image.onload = function () {
        return callback({
          naturalHeight: image.naturalHeight,
          naturalWidth: image.naturalWidth,
          src: image.src
        })
      }
      image.src = src
    }

    onMounted(() => {
      parentComponentMounted.value = true
    })

    const obeserveComponent = h(LazyComponent, {
      onShow: () => {
        if (parentComponentMounted.value && !show.value) {
          imageLoadedAsync(imgSrc, () => show.value = true)
        }
      }
    }, null)

    return () => show.value
      ? h(Transition, {
          name,
          style,
          mode: 'out-in',
          appear: true
        }, children)
      : obeserveComponent
  }
})
</script>

<style lang="less">
.animate-image--box {

  .image-description {
    text-align: center;

    span {
      opacity: 0;
      transition: opacity .3s cubic-bezier(.78,.14,.15,.86);
    }
  }

  &:hover {

    .image-description span {
      opacity: 1;
    }
  }
}
</style>